package com.zhangzhan.gulimallware.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhangzhan.gulimallcommcon.enums.OrderStatusEnum;
import com.zhangzhan.gulimallcommcon.tos.SkuCheckInventoryTo;
import com.zhangzhan.gulimallcommcon.tos.WareOrderUnLockTo;
import com.zhangzhan.gulimallcommcon.util.MyCollUtil;
import com.zhangzhan.gulimallcommcon.util.PageUtils;
import com.zhangzhan.gulimallcommcon.util.Query;
import com.zhangzhan.gulimallware.dao.WareSkuDao;
import com.zhangzhan.gulimallware.entity.WareOrderTaskDetailEntity;
import com.zhangzhan.gulimallware.entity.WareOrderTaskEntity;
import com.zhangzhan.gulimallware.entity.WareSkuEntity;
import com.zhangzhan.gulimallware.service.WareOrderTaskDetailService;
import com.zhangzhan.gulimallware.service.WareOrderTaskService;
import com.zhangzhan.gulimallware.service.WareSkuService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.zhangzhan.gulimallcommcon.constant.orderAndWareUnLockCons.WareUnLockConstant.WARE_EVENT_EXCHANGE;
import static com.zhangzhan.gulimallcommcon.constant.orderAndWareUnLockCons.WareUnLockConstant.WARE_UNLOCK_WARE;


@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {

    @Autowired
    private WareOrderTaskDetailService wareOrderTaskDetailService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private WareOrderTaskService wareOrderTaskService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params),
                new QueryWrapper<WareSkuEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPageDetail(Map<String, Object> params) {

        String skuId = (String) params.get("skuId");
        String wareId = (String) params.get("wareId");

        LambdaQueryWrapper<WareSkuEntity> wrapper = Wrappers.<WareSkuEntity>lambdaQuery()
                .eq(StrUtil.isNotBlank(skuId), WareSkuEntity::getSkuId, skuId)
                .eq(StrUtil.isNotBlank(wareId), WareSkuEntity::getWareId, wareId);

        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public List<SkuCheckInventoryTo> checkInventory(List<Long> skuIds) {
        List<SkuCheckInventoryTo> skuCheckInventoryTos = skuIds.stream().map(skuId -> {
            SkuCheckInventoryTo skuCheckInventoryTo = new SkuCheckInventoryTo();
            skuCheckInventoryTo.setSkuId(skuId);

            WareSkuEntity wareSkuEntity = this.getOne(Wrappers.<WareSkuEntity>lambdaQuery()
                    .eq(WareSkuEntity::getSkuId, skuId));

            int count = 0;
            if (!Objects.equals(Optional.of(wareSkuEntity.getStockLocked()).orElse(0), 0)) {
                count = wareSkuEntity.getStock() - wareSkuEntity.getStockLocked();
            } else {
                count = wareSkuEntity.getStock();
            }

            skuCheckInventoryTo.setCheck(count > 0);

            return skuCheckInventoryTo;
        }).toList();

        return skuCheckInventoryTos;
    }

    /**
     * @param map
     * @return java.lang.Boolean
     * @description 锁定库存
     * @author zhangyiheng
     * @date 2024/7/1 14:30
     */
    @Override
    @Transactional
    public Boolean lockInventory(Map<Long, Integer> map, String orderSn) {
        if (CollUtil.isNotEmpty(map) && Objects.nonNull(orderSn)) {

            List<Long> taskIds = new ArrayList<>();

            for (Map.Entry<Long, Integer> entry : map.entrySet()) {
                Long skuId = entry.getKey();
                Integer count = entry.getValue();


                //查询所有仓库包含skuId商品有库存的数据
                List<WareSkuEntity> wareSkuEntities = this.getBaseMapper().getSkuInventory(skuId);


                if (MyCollUtil.isNotEmpty(wareSkuEntities)) {
                    boolean lock = false;

                    //更新锁定库存
                    for (WareSkuEntity wareSku : wareSkuEntities) {
                        Integer res = this.getBaseMapper().updateStockLock(wareSku.getWareId(), skuId, count);
                        if (Objects.equals(res, 1)) {
                            //修改成功 库存充足

                            //存储库存工作单配送状态信息
                            WareOrderTaskEntity wareOrderTaskEntity = new WareOrderTaskEntity();
                            wareOrderTaskEntity.setOrderSn(orderSn);
                            wareOrderTaskEntity.setTaskStatus(OrderStatusEnum.CREATE_NEW.getCode());
                            wareOrderTaskEntity.setWareId(wareSku.getWareId());
                            wareOrderTaskEntity.setCreateTime(new Date());
                            wareOrderTaskEntity.setTrackingNo(IdUtil.fastSimpleUUID());
                            wareOrderTaskService.save(wareOrderTaskEntity);


                            //存储库存工作单（回滚所需数据）
                            WareOrderTaskDetailEntity wareOrderTaskDetailEntity = new WareOrderTaskDetailEntity();
                            wareOrderTaskDetailEntity.setSkuId(skuId);
                            wareOrderTaskDetailEntity.setSkuName("");
                            wareOrderTaskDetailEntity.setSkuNum(count);
                            wareOrderTaskDetailEntity.setWareId(wareSku.getWareId());
                            wareOrderTaskDetailEntity.setTaskId(wareOrderTaskEntity.getId());
                            wareOrderTaskDetailEntity.setState(1);
                            wareOrderTaskDetailService.save(wareOrderTaskDetailEntity);

                            taskIds.add(wareOrderTaskEntity.getId());

                            lock = true;
                            break;
                        }
                    }

                    if (!lock) {
                        throw new RuntimeException("商品:" + skuId + "库存不足。");
                    }
                } else {
                    throw new RuntimeException("商品:" + skuId + "库存不足。");
                }
            }

            WareOrderUnLockTo wareOrderUnLockTo = new WareOrderUnLockTo();
            wareOrderUnLockTo.setOrderSn(orderSn);
            wareOrderUnLockTo.setTaskIds(taskIds);
            //库存确定锁定成功，加入死信队列
            //String exchange, String routingKey, Object object
            try {
                rabbitTemplate.convertAndSend(WARE_EVENT_EXCHANGE, WARE_UNLOCK_WARE, wareOrderUnLockTo);
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("库存解锁队列传送失败");
            }

            return true;
        }
        return false;
    }

    @Override
    public Boolean unLock(Long skuId, Long wareId, Integer count) {
        Integer res = this.getBaseMapper().unLock(wareId, skuId, count);
        return Objects.equals(res, 1);
    }

}